﻿#region LICENSE
/****************************************************************************
 *                                                                          *
 *  CoderBlu.Collections - Thread-safe Collections                          *
 *  Copyright (C) 2008 Rodger "Nullz" Aiken <nullz.void@gmail.com>          *
 *                                                                          *
 *  This library is free software; you can redistribute it and/or modify    *
 *  it under the terms of the GNU Library General Public License as         *
 *  published by the Free Software Foundation; either version 2 of the      *
 *  License, or (at your option) any later version.                         *
 *                                                                          *
 *  This library is distributed in the hope that it will be useful, but     *
 *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT     *
 *  ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library        *
 *  General Public License for more details.                                *
 *                                                                          *
 *  You should have received a copy of the GNU Library General Public       *
 *  License along with this library; if not, write to the Free Foundation,  *
 *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA        *
 *                                                                          *
 ****************************************************************************/
#endregion

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Text;
using System.Text.RegularExpressions;

namespace CoderBlu.Collections
{
	[Serializable]
	public class BinaryTreeNode<T>
	{
		internal BinaryTreeBase<T> _tree;
		internal BinaryTreeNode<T> _lnode;
		internal BinaryTreeNode<T> _rnode;
		private T _value;

		public BinaryTreeNode ( T value )
			: this(value, null, null) {
		}

		protected BinaryTreeNode ( T value, BinaryTreeNode<T> left, BinaryTreeNode<T> right ) {
			this._value = value;
			this._lnode = left;
			this._rnode = right;
		}

		public BinaryTreeBase<T> Tree {
			get { return this._tree; }
		}

		public BinaryTreeNode<T> Left {
			get { return this._lnode; }
			protected set { this._lnode = value; }
		}

		public BinaryTreeNode<T> Right {
			get { return this._rnode; }
			protected set { this._rnode = value; }
		}

		public T Value {
			get { return this._value; }
			set { this._value = value; }
		}
	}

	[Serializable]
	public abstract class BinaryTreeBase<T> :
		SynchronizedCollection,
		ICollection, ICollection<T>,
		IEnumerable, IEnumerable<T>,
		ISerializable, IDeserializationCallback
	{
		private SerializationInfo _info;
		private BinaryTreeNode<T> _root;
		private volatile int _count;

		public Node Base {
			get {
				lock ( this._synclock )
					return this._root;
			}
			protected set {
				lock ( this._synclock )
					this._root = value;
			}
		}

		public int Count {
			get { return this._count; }
		}

		public BinaryTreeNode<T> AttachLeft ( BinaryTreeNode<T> node, BinaryTreeNode<T> newNode ) {
			
		}

		public void InOrder ( Action<T> action ) {
			if ( this._count > 0 ) {
				lock ( this._synclock )
					this.InOrder(this._root, action);
			}
		}
		public void InOrder ( BinaryTreeNode<T> node, Action<T> action ) {
			if ( node == null )
				throw new ArgumentNullException("node");

			if ( node._tree != this )
				throw new ArgumentException("Node is not a member of this tree", "node");

			if ( action == null )
				throw new ArgumentNullException("action");

			lock ( this._synclock ) {
				if ( node._lnode != null )
					this.InOrder(node._lnode, action);

				action(node.Value);

				if ( node._rnode != null )
					this.InOrder(node._rnode, action);
			}
		}

		public void PreOrder ( Action<T> action ) {
			if ( this._count > 0 ) {
				lock ( this._synclock )
					this.PreOrder(this._root, action);
			}
		}
		public void PreOrder ( BinaryTreeNode<T> node, Action<T> action ) {
			if ( node == null )
				throw new ArgumentNullException("node");

			if ( node._tree != this )
				throw new ArgumentException("Node is not a member of this tree", "node");

			if ( action == null )
				throw new ArgumentNullException("action");

			lock ( this._synclock ) {
				action(node.Value);

				if ( node._lnode != null )
					this.PreOrder(node._lnode, action);

				if ( node._rnode != null )
					this.PreOrder(node._rnode, action);
			}
		}

		public void PostOrder ( Action<T> action ) {
			if ( this._count > 0 ) {
				lock ( this._synclock )
					this.PostOrder(this._root, action);
			}
		}
		public void PostOrder ( BinaryTreeNode<T> node, Action<T> action ) {
			if ( node == null )
				throw new ArgumentNullException("node");

			if ( node._tree != this )
				throw new ArgumentException("Node is not a member of this tree", "node");

			if ( action == null )
				throw new ArgumentNullException("action");

			lock ( this._synclock ) {
				if ( node._lnode != null )
					this.PostOrder(node._lnode, action);

				if ( node._rnode != null )
					this.PostOrder(node._rnode, action);

				action(node.Value);
			}
		}
	}
}